package com.yonyou.brigade.ybz.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.yonyou.brigade.ybz.model.CnvOutentitydef;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


public class MakeRegisterString {
    private static ICnvOutentitydefService cnvOutentitydefService;

    private static  String PREFIX="G001ZM0000$$$$$$";
    private static String ENTITYPREFIX="G001ZM0000$$$$$$ENTITY";
    private int ENTITYNUM=10;
    private Map<String,String> MAPENTITIES=new HashMap<>();
    private StringBuilder StrBuilder=new StringBuilder();
    private int  NUM=1000;
    private static String TYPENAME="";
    private static String TYPECODE="";
    /*
     * 编码 * 实体关系类型  * 列名（字段code） * 字段类型 * 字段名称 * 字段长度 * 属性名（字段code） * 关系实体ID * 所属实体ID
     * */
    private String TEMPLATE="INSERT INTO `cnv_attribute` VALUES " +
            "('"+PREFIX+"%s', %s, '%s',%s, '', NULL, " +
            "'%s', b'0', b'0', b'0', %d, b'1', 0, " +
            "'%s', %s, NULL, NULL," +
            " '%s', NULL, NULL, NULL, now());\r\n";

    private MakeRegisterString(){

    }

    public static  MakeRegisterString getInstance(String typeCode,String typeName,ICnvOutentitydefService cnvOutentitydefServices)
    {
        TYPENAME=typeName;
        TYPECODE=typeCode;
        cnvOutentitydefService=cnvOutentitydefServices;
        PREFIX=PREFIX.replace("$$$$$$",typeCode.replaceAll("_","").toUpperCase());
        ENTITYPREFIX=ENTITYPREFIX.replace("$$$$$$",typeCode.replaceAll("_","").toUpperCase());
        return new MakeRegisterString();
    }

    public String getRegisterSQL(String json)
    {
        //json=json.replace("，",",").replace("。",",");
        String rootEntity=ENTITYPREFIX + String.format("%0" + (36 - ENTITYPREFIX.length()) + "d", ENTITYNUM);
        makeTypeTrade(TYPENAME,TYPECODE,rootEntity);
        MAPENTITIES.put(rootEntity,TYPENAME);
        JSONObject jsonObj = JSONObject.parseObject(json);
        dealSourceData(jsonObj,rootEntity);
        makeEntity();
        makeOutRefEntitySQL(TYPECODE,rootEntity);
        return  StrBuilder.toString();
    }

    public  void makeTypeTrade(String typeName,String typeCode,String rootEntity)
    {
        String[] codes = typeCode.split("_");
        String type = "";
        for (String code : codes) {
            type = type + code.toUpperCase();
        }
        String billTypeCode = "G001ZM0000" + type + "BILLTYPE";
        String billTypeId = String.format("%0" + (36 - billTypeCode.length()) + "d", 10);

        String tradeTypeCode = "G001ZM0000" + type + "TRADETYPE";
        String tradeTypeId = String.format("%0" + (36 - tradeTypeCode.length()) + "d", 10);

        StrBuilder.append(
                "INSERT INTO `cnv_billtype` VALUES ('" + billTypeCode + billTypeId + "', b'1', '"+typeCode+"_billtype', b'1', '"+typeName+"单据类型', NULL, '"+rootEntity+"', now());\r\n" +
                "INSERT INTO `cnv_billtype` VALUES ('" + tradeTypeCode + tradeTypeId +"', b'0', '"+typeCode+"_tradetype', b'1', '"+typeName+"交易类型', '"+typeCode+"_billtype', NULL, now());\r\n");
    }

    public void makeEntity()
    {
        if(MAPENTITIES.size()>0)
        {
           Iterator iterator= MAPENTITIES.keySet().iterator();
           while (iterator.hasNext())
           {
               String key=(String)iterator.next();
               String value=(String)MAPENTITIES.get(key);
               StrBuilder.append("INSERT INTO `cnv_entity` VALUES ('"+key+"', '"+value+"', '"+key+"', now());\r\n");
           }
        }
    }

    public void makeOutRefEntitySQL(String typeCode,String rootEntity)
    {
        String code=getOutRefEntityCode();
        StrBuilder.append(" INSERT INTO `cnv_outentitydef` VALUES ('"+code+"', '"+typeCode+"_billtype', '"+rootEntity+"', b'1', NULL, now());\r\n");

    }


    private String getOutRefEntityCode( )
    {
        String outCode="";
        Wrapper<CnvOutentitydef> cnvOutentitydefWrapper=new EntityWrapper<>();
        cnvOutentitydefWrapper.where("1={0}",1);
        cnvOutentitydefWrapper.orderBy("id",false);
        List<CnvOutentitydef> cnvOutentitydefs=  cnvOutentitydefService.selectList(null);
        if(cnvOutentitydefs!=null&&cnvOutentitydefs.size()>0)
        {
            outCode=cnvOutentitydefs.get(cnvOutentitydefs.size()-1).getId();
            outCode=increase(outCode);
        }
        return outCode;
    }

    public  String increase(String value){
        int index=30;
        int n=Integer.parseInt(value.substring(index))+1;
        String newValue=String.valueOf(n);
        int len=value.length()-newValue.length()-index;

        for(int i=0;i<len;i++){
            newValue="0"+newValue;
        }
        return value.substring(0,index)+newValue;
    }

    private  void dealSourceData(JSONObject jsonObj,String ownerEntity)
    {
        Iterator it = jsonObj.keySet().iterator();
        while(it.hasNext()){

            String key=(String)it.next();
            Object value=jsonObj.get(key);
            if(value instanceof JSONArray)
            {
                NUM++;
                String []fieldInfo= ((String) key).split(",");
                ENTITYNUM++;
                String newEntity=ENTITYPREFIX + String.format("%0" + (36 - ENTITYPREFIX.length()) + "d", ENTITYNUM);
                StrBuilder.append(String.format(TEMPLATE,String.format("%0" + (36 - PREFIX.length()) + "d", NUM),getRefCodeByType(fieldInfo[1]),
                        fieldInfo[0],getCodeByType(fieldInfo[1]),fieldInfo[2],100,fieldInfo[0],
                        "'" + newEntity + "'",ownerEntity,null));
                MAPENTITIES.put(newEntity,fieldInfo[2]);
                dealSourceData(((JSONArray)value).getJSONObject(0),newEntity);

            }
            else if(value instanceof  JSONObject)
            {
                NUM++;
                String []fieldInfo= ((String) key).split(",");
                ENTITYNUM++;
                String newEntity=ENTITYPREFIX + String.format("%0" + (36 - ENTITYPREFIX.length()) + "d", ENTITYNUM);
                StrBuilder.append(String.format(TEMPLATE,String.format("%0" + (36 - PREFIX.length()) + "d", NUM),getRefCodeByType(fieldInfo[1]),
                        fieldInfo[0],getCodeByType(fieldInfo[1]),fieldInfo[2],100,fieldInfo[0],
                        "'" + newEntity + "'",ownerEntity,null));
                MAPENTITIES.put(newEntity,fieldInfo[2]);
                dealSourceData((JSONObject)(value),newEntity);
            }
            else if(value instanceof  String)
            {
                NUM++;
                String []fieldInfo= ((String) key).split(",");
                StrBuilder.append(String.format(TEMPLATE,String.format("%0" + (36 - PREFIX.length()) + "d", NUM),getRefCodeByType(fieldInfo[1]),
                        fieldInfo[0],getCodeByType(fieldInfo[1]),fieldInfo[2],getLengthByField(key),fieldInfo[0],
                        null,ownerEntity,null));
            }

        }
    }

    private static int getRefCodeByType(String type)
    {
        String lowerType=type.toLowerCase();
        if(lowerType.equals("jsonarray"))
        {
            return 40;
        }
        else if (lowerType.equals("jsonobject"))
        {
            return 20;
        }
        else if(lowerType.equals("string"))
        {
            return 10;
        }
        return 10;
    }

    private static  int getCodeByType(String type)
    {
        if(type.toLowerCase().equals("string"))
        {
            return 6;
        }
        else if(type.toLowerCase().equals("boolean") || type.toLowerCase().equals("bool"))
        {
            return 7;
        }
        else if(type.toLowerCase().equals("int"))
        {
            return  1;
        }
        else if(type.toLowerCase().equals("long"))
        {
            return  2;
        }
        else if(type.toLowerCase().equals("double"))
        {
            return  4;
        }
        else if(type.toLowerCase().equals("bigdecimal") || type.toLowerCase().equals("decimal"))
        {
            return 5;
        }
        else if(type.toLowerCase().equals("date"))
        {
            return 8;
        }
        else if(type.toLowerCase().equals("time"))
        {
            return  9;
        }
        else if(type.toLowerCase().equals("sqldatetime"))
        {
            return 10;
        }
        else if(type.toLowerCase().equals("datetime"))
        {
            return 15;
        }
        else if(type.toLowerCase().equals("jsonarray"))
        {
            return 11;
        }
        else if(type.toLowerCase().equals("jsonobject"))
        {
            return 11;
        }
        return 0;
    }

    private static int getLengthByField(String fieldInfo)
    {
       String[] fields=fieldInfo.split(",");
       int code=getCodeByType(fields[1]);
       if (fields.length > 3){
           return Integer.parseInt(fields[3]);
       } else {
           if(code==6)
           {
               return 512;
           }
           else if(code==7)
           {
               return 6;
           }
           else if(code==1)
           {
               return 11;
           }
           else if(code==4)
           {
               return 64;
           }
           else if(code==5)
           {
               return 26;
           }
           else if(code==8)
           {
               return 32;
           }
           else if(code==9)
           {
               return  32;
           }
           else if(code==10||code==15)
           {
               return 32;
           }
           else if(code==11)
           {
               return 100;
           }
       }
        return 100;
    }
}